import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

iris=load_iris()
df=pd.DataFrame(iris.data,columns=iris.feature_names)
df['label']=iris.target

data0=df.loc[df['label'].isin([0]),:]
data1=df.loc[df['label'].isin([1]),:]
data2=df.loc[df['label'].isin([2]),:]

pos_data=data0
neg_data=neg_data=pd.concat([data1,data1])
# 取出花瓣长度、花瓣宽度以及分类
data=np.array(pd.concat([pos_data,neg_data])[['sepal length (cm)','sepal width (cm)','label']])
# data=np.array(pd.concat([pos_data,neg_data]))
# X是长度和宽度，y是分类
X, y = data[:, :-1], data[:, -1]
y = np.array([1 if i == 1 else -1 for i in y])


class Model:
    def __init__(self,lr=0.2,epoches_limit=5000):
        self.w = np.ones(len(data[0]) - 1, dtype=np.float32)  # 初始化权重
        self.b = 0  # 初始化截距
        self.l_rate = lr  # 学习步长
        self.epoches=0
        self.epoches_limit=epoches_limit

    # 符号函数
    def sign(self, x, w, b):
        y = np.dot(x, w) + b
        return y

    # 进行感知训练
    def fit(self, X_train, y_train):
        wrong=True
        while wrong:
            wrong_count = 0
            for d in range(len(X_train)):
                X = X_train[d]
                y = y_train[d]
                if y * self.sign(X, self.w, self.b) <= 0:#classification is wrong,[-1,>0]ot[1,<0]
                    self.w = self.w + self.l_rate * np.dot(0.5*y, X)  # 更新权重
                    self.b = self.b + self.l_rate * y  # 更新步长
                    wrong_count += 1
            if wrong_count == 0:
                wrong = False
            self.epoches+=1
            if self.epoches==self.epoches_limit:
                return -1,"Nonlinear Data,I can't solve it TAT"
        return 0,'Perceptron Model!'

perceptron = Model()
flag,str=perceptron.fit(X, y)
if flag==0:
    print(perceptron.w)
    print(perceptron.b)
    x_points = np.linspace(1, 4, 10)

    y_ = -(perceptron.w[0] * x_points + perceptron.b) / perceptron.w[1]
    plt.plot(x_points, y_)

    plt.plot(pos_data.iloc[:,0], pos_data.iloc[:,1], 'bo', color='blue', label='0')
    plt.plot(neg_data.iloc[:, 0], neg_data.iloc[:, 1], 'bo', color='orange', label='1')
    plt.xlabel('petal length')
    plt.ylabel('petal width')
    plt.legend()
    plt.show()
else:
    print(str)